package com.lry.util.requestcore;


import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.util.Collections;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

/**
 * http请求工具；hutool:5.8.x
 *
 * @author ALI
 * @since 2023/5/15
 */
@Slf4j
public class MyHttpUtil {

    public static final String PARAM_SEP = "?";
    public static final String PARAM_SPL = "&";

    public static String buildUrl(String baseUrl, String api) {
        if (StringUtils.isBlank(api)) {
            return baseUrl;
        }
        if (api.startsWith("http")) {
            return api;
        }
        return StringUtils.removeEnd(baseUrl, "/") + "/" + StringUtils.removeStart(api, "/");
    }

    public static HttpResponse get(String url, Map<String, String> headers, Map<String, Object> param) {
        return request(Method.GET, url, headers, param, null);
    }

    public static HttpResponse get(String url, Map<String, Object> param) {
        return request(Method.GET, url, null, param, null);
    }

    public static HttpResponse post(String url, Object body) {
        return request(Method.POST, url, null, null, body);
    }

    public static HttpResponse post(String url, Map<String, String> headers, Object body) {
        return request(Method.POST, url, headers, null, body);
    }

    /**
     * 请求封装
     *
     * @param method    请求方式
     * @param url       请求url
     * @param parameter 参数
     */
    public static HttpResponse request(Method method, String url, Map<String, String> headers,
                                       Map<String, Object> parameter, Object body) {
        HttpRequest request = null;
        String queryParameter = buildGetParameter(parameter);
        String sep = PARAM_SEP;
        if (url.contains(PARAM_SEP)) {
            sep = PARAM_SPL;
        }
        if (StringUtils.isNotBlank(queryParameter)) {
            url = url + sep + queryParameter;
        }
        request = HttpUtil.createRequest(method, url);
        String bodyJson = "";
        if (body == null) {
            bodyJson = "{}";
        } else {
            if (body instanceof String) {
                bodyJson = body.toString();
            } else {

                bodyJson = JSON.toJSONString(body);
            }
        }
        if (isForm(headers)) {
            Map<String, Object> form = (Map<String, Object>) body;
            request.form(form);
        } else {
            request.body(bodyJson);
        }
        addHeader(request, headers);
        request.timeout(1200000);
        try (HttpResponse execute = request.execute()) {
            if (!execute.isOk()) {
                log.error("请求失败");
                log.error("调用第三方服务器请求错误！url：{}", request.getUrl());
                log.error("失败状态：{}，失败信息：{}", execute.getStatus(), execute.body());
            }
            return execute;
        } catch (Exception e) {
            log.error("url:{}", url);
            log.error("body:{}", bodyJson);
            log.error("请求异常！" + e.getMessage(), e);
            throw e;
        }
    }

    public static boolean isForm(Map<String, String> headers) {
        if (headers == null || headers.isEmpty()) {
            return false;
        }
        for (String value : headers.values()) {
            if (value.toLowerCase().contains("form-data")) {
                return true;
            }
        }
        return false;
    }

    /**
     * 支持的是结果中的目标对象时一个对象，不是基本类型
     *
     * @param body      响应数据
     * @param fieldPath json路径，符合“&&”连接多个要获取的对象，如果是对象，会进行数据合并
     * @return list<JSONObject> list里的是对象，不是基本类型
     */
    public static JSONArray getArrayObject(String body, String fieldPath) {
        if (StringUtils.isBlank(body)) {
            throw new RuntimeException("无响应数据，响应是空的！");
        }
        JSONObject jsonObject = JSON.parseObject(body);
        String[] split = fieldPath.split("\\.");
        Object o = null;
        if (split.length == 1) {
            o = jsonObject.get(split[0]);
        } else {
            JSONObject temp = jsonObject;
            for (int i = 0; i < split.length - 1; i++) {
                temp = temp.getJSONObject(split[i]);
            }
            if (temp == null) {
                throw new RuntimeException("响应里指定字段没有数据：dataField=" + fieldPath + "，响应结果：" + body);
            }
            o = temp.get(split[split.length - 1]);
        }
        if (o == null) {
            return new JSONArray();
        }
        if (o instanceof JSONObject) {
            return new JSONArray(Collections.singletonList(o));
        }
        return (JSONArray) o;
    }
    //    public static JSONArray getArrayObject(String body, String fieldPath) {
    //        if (StringUtils.isBlank(body)) {
    //            throw new RuntimeException("无响应数据，响应是空的！");
    //        }
    //        JSONObject jsonObject = JSON.parseObject(body);
    //        if (fieldPath.contains("&&")) {
    //            JSONArray result = new JSONArray();
    //            String[] split = fieldPath.split("&&");
    //            for (String fp : split) {
    //                JSONArray ja = getPathObj(jsonObject, fp);
    //                result.addAll(ja);
    //            }
    //            if (split[1].startsWith(split[0]) || split[0].startsWith(split[1])) {
    //                // 表示嵌套对象，需要合并
    //                result.getJSONObject(0).putAll(result.getJSONObject(1));
    //                result.remove(2);
    //                return result;
    //            } else {
    //                // 表示同级不需要合并
    //            }
    //
    //
    //            return result;
    //        } else if (fieldPath.contains("&+")) {
    //
    //        }
    //        return getPathObj(jsonObject, fieldPath);
    //    }

    public static void check(HttpResponse httpResponse) {
        if (httpResponse == null || httpResponse.getStatus() >= 500) {
            throw new RuntimeException("远程服务异常！" + httpResponse.body());
        }
        if (401 == httpResponse.getStatus()) {
            throw new RuntimeException("认证失败！" + httpResponse.body());
        }
        if (400 < httpResponse.getStatus() && httpResponse.getStatus() < 500) {
            throw new RuntimeException("参数或认证失败！" + httpResponse.body());
        }
    }

    private static JSONArray getPathObj(JSONObject jsonObject, String fieldPath) {
        String[] split = fieldPath.split("\\.");
        Object o = null;
        if (split.length == 1) {
            o = jsonObject.get(split[0]);
        } else {
            JSONObject temp = jsonObject;
            for (int i = 0; i < split.length - 1; i++) {
                temp = temp.getJSONObject(split[i]);
            }
            if (temp == null) {
                return new JSONArray();
            }
            o = temp.get(split[split.length - 1]);
        }
        if (o == null) {
            return new JSONArray();
        }
        if (o instanceof JSONObject) {
            return new JSONArray(Collections.singletonList(o));
        }
        return (JSONArray) o;
    }

    /**
     * 格尔的认证 + 签名（封装）
     *
     * @param http 请求对象
     */
    private static void addHeader(HttpRequest http, Map<String, String> headers) {
        http.header(Header.CONTENT_TYPE, "application/json;charset=utf-8");
        if (headers == null || headers.isEmpty()) {
            return;
        }
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            http.header(entry.getKey(), entry.getValue());
        }
    }

    /**
     * 构建get参数
     *
     * @param parameter 参数对象
     */
    private static String buildGetParameter(Map<String, Object> parameter) {
        StringBuilder parameterStr = new StringBuilder();
        if (parameter != null && !parameter.isEmpty()) {
            for (Map.Entry<String, Object> entry : parameter.entrySet()) {
                parameterStr.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
            return StringUtils.removeEnd(parameterStr.toString(), "&");
        }
        return "";
    }

}
